#include "glenv.h"

Ptr< GlControl > _control;

void handle_display ();
void handle_reshape (int width, int height);
void handle_timer (int val);
void handle_key (unsigned char key, int x, int y);
void handle_special (int key, int x, int y);
void handle_mouse (int button, int state, int x, int y);
void handle_motion (int x, int y);
void handle_passive_motion (int x, int y);

void glenv_create_window (UINT mode, const char* title, bool isFullScreen,
                          int width, int height, int posX, int posY)
{
  glutInitDisplayMode (mode);
  if (!isFullScreen)
  {
    if (posX >= 0 && posY >= 0)
      glutInitWindowPosition (posX, posY);
    if (width > 0 && height > 0)
      glutInitWindowSize (width, height);
    glutCreateWindow (title);
  }
  else
  {
    glutCreateWindow (title);
    glutFullScreen ();
  }
}


void glenv_run (Ptr< GlControl > control)
{
  _control = control;
  _control->init_render ();

  glutDisplayFunc (handle_display);
  glutReshapeFunc (handle_reshape);
  glutKeyboardFunc (handle_key);
  glutSpecialFunc (handle_special);
  glutMouseFunc (handle_mouse);
  glutMotionFunc (handle_motion);
  glutPassiveMotionFunc (handle_passive_motion);

  if (control->getTimerDuration () > 0)
    glutTimerFunc (control->getTimerDuration (), handle_timer, 0);

  glutMainLoop ();
}


void handle_display ()
{
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();
  _control->draw ();
  glutSwapBuffers ();
}


void handle_reshape (int width, int height)
{
  _control->handle_reshape (width, height);
}


void handle_timer (int val)
{
  val = _control->handle_timer (val);
  glutTimerFunc (_control->getTimerDuration (), handle_timer, val);
  glutPostRedisplay ();
}


void handle_key (unsigned char key, int x, int y)
{
  _control->handle_keypress (key, x, y);
  glutPostRedisplay ();
}


void handle_special (int key, int x, int y)
{
  _control->handle_special_keypress (key, x, y);
  glutPostRedisplay ();
}

void handle_mouse (int button, int state, int x, int y)
{
  _control->handle_mouse (button, state, x, y);
  glutPostRedisplay ();
}

void handle_motion (int x, int y)
{
  _control->handle_motion (x, y);
  glutPostRedisplay ();
}

void handle_passive_motion (int x, int y)
{
  _control->handle_passive_motion (x, y);
  glutPostRedisplay ();
}